// Copyright (C) 1953-2022 NUDT
// Verilog module name - synchronous_packet_encapsulate
// Version: V4.1.0.20220628
// Created:
//         by - fenglin 
////////////////////////////////////////////////////////////////////////////
// Description:
//         synchronous_packet_encapsulate
///////////////////////////////////////////////////////////////////////////

`timescale 1ns/1ps

module synchronous_packet_encapsulate #(parameter osm_id = 8'h0,local_module_id = 12'd1)
(
    i_clk                  ,
    i_rst_n                ,
    
    iv_hcp_mid             ,
    iv_opensync_dst_module_id ,
    
    i_data_fifo_empty      ,
    o_data_fifo_rd         ,
    iv_data_fifo_rdata     ,
                          
    i_diagest_fifo_empty   ,
    o_diagest_fifo_rd      ,
    iv_diagest_fifo_rdata  ,
                           
    ov_data                ,
    o_data_wr               
    
);
// I/O
// clk & rst
input                   i_clk  ;
input                   i_rst_n;
//input
input       [11:0]      iv_hcp_mid         ;
input       [11:0]      iv_opensync_dst_module_id;

input                   i_data_fifo_empty  ;
output  reg             o_data_fifo_rd     ;
input       [8:0]       iv_data_fifo_rdata ;

input                   i_diagest_fifo_empty  ;
output  reg             o_diagest_fifo_rd     ;
input       [59:0]      iv_diagest_fifo_rdata ;
//output
output  reg [8:0]       ov_data;
output  reg             o_data_wr;
//***************************************************
//         opensync protocol encapsulate
//***************************************************
reg      [5:0]      rv_transmit_byte_cnt;
reg      [3:0]      rv_ptp_messagetype  ;
reg      [39:0]     rv_local_count_rx   ;
reg      [3:0]      rv_spe_state;
localparam  IDLE_S                           = 4'd0,
            TRANSMIT_OPENSYNC_S              = 4'd1,
            TRANSMIT_PTPPCF_1ST_CYCLE_S      = 4'd2,
            TRANSMIT_PTPPCF_MIDDLE_CYCLE_S   = 4'd3,
            TRANSMIT_NOT_PTPPCF_1ST_CYCLE_S  = 4'd4,
            TRANSMIT_NOT_PTPPCF_MIDDLE_CYCLE_S = 4'd5;
                        
always@(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n) begin
        ov_data             <= 9'b0;
        o_data_wr           <= 1'b0;
        
        o_data_fifo_rd      <= 1'b0;
        o_diagest_fifo_rd   <= 1'b0;
        
        rv_ptp_messagetype  <= 4'b0;
        rv_transmit_byte_cnt<= 6'b0;
        rv_local_count_rx   <= 40'b0;

        rv_spe_state        <= IDLE_S;
    end
    else begin
        case(rv_spe_state)
            IDLE_S:begin         
                if(!i_diagest_fifo_empty)begin//judge eth_type                 
                    if(iv_diagest_fifo_rdata[15:0] == 16'h88f7)begin//ptp.
                        ov_data             <= 9'h166;
                        o_data_wr           <= 1'b1; 
                        
                        o_data_fifo_rd      <= 1'b0;
                        o_diagest_fifo_rd   <= 1'b1;
                        
                        rv_local_count_rx   <= iv_diagest_fifo_rdata[59:20];
                        rv_ptp_messagetype  <= iv_diagest_fifo_rdata[19:16];
                        rv_transmit_byte_cnt<= rv_transmit_byte_cnt + 1'b1;   
                        
                        rv_spe_state        <= TRANSMIT_OPENSYNC_S;
                    end
                    else begin
                        ov_data             <= 9'b0;
                        o_data_wr           <= 1'b0;

                        o_data_fifo_rd      <= 1'b1;
                        o_diagest_fifo_rd   <= 1'b1;

                        rv_ptp_messagetype  <= 4'b0;
                        rv_transmit_byte_cnt<= 6'b0;
                        rv_local_count_rx   <= 40'b0;
                  
                        rv_spe_state        <= TRANSMIT_NOT_PTPPCF_1ST_CYCLE_S;
                    end
                end 
                else begin
                    ov_data             <= 9'b0;
                    o_data_wr           <= 1'b0;
                    
                    o_data_fifo_rd      <= 1'b0;
                    o_diagest_fifo_rd   <= 1'b0;
                    
                    rv_ptp_messagetype  <= 4'b0;
                    rv_transmit_byte_cnt<= 6'b0;
                    rv_local_count_rx   <= 40'b0;

                    rv_spe_state        <= IDLE_S;
                end
            end							
            TRANSMIT_OPENSYNC_S:begin                                     
                o_data_wr           <= 1'b1;
                o_diagest_fifo_rd   <= 1'b0;
                rv_transmit_byte_cnt<= rv_transmit_byte_cnt + 1'b1; 
                case(rv_transmit_byte_cnt)
                    6'd1 :ov_data             <= 9'h026;
                    6'd2 :ov_data             <= 9'h062;
                    6'd3 :ov_data             <= {1'b0,iv_hcp_mid[11:4]};
                    6'd4 :ov_data             <= {1'b0,iv_hcp_mid[3:0],iv_opensync_dst_module_id[11:8]};
                    6'd5 :ov_data             <= {1'b0,iv_opensync_dst_module_id[7:0]}; 
                    6'd6 :ov_data             <= 9'h066;
                    6'd7 :ov_data             <= 9'h026;
                    6'd8 :ov_data             <= 9'h062;
                    6'd9 :ov_data             <= {1'b0,iv_hcp_mid[11:4]};
                    6'd10:ov_data             <= {1'b0,iv_hcp_mid[3:0],local_module_id[11:8]};
                    6'd11:ov_data             <= {1'b0,local_module_id[7:0]}; 
                    6'd12:ov_data    <= {1'b0,8'hff};
                    6'd13:ov_data    <= {1'b0,8'h01};
                    6'd14:ov_data    <= {1'b0,8'h06};
                    6'd15:begin
                        if(rv_ptp_messagetype == 4'h0)begin//sync
                            ov_data    <= {1'b0,8'h01};
                        end
                        else if(rv_ptp_messagetype == 4'h2)begin//Pdelay_req
                            ov_data    <= {1'b0,8'h02};
                        end
                        else if(rv_ptp_messagetype == 4'h3)begin//Pdelay_resp
                            ov_data    <= {1'b0,8'h03};
                        end
                        else if(rv_ptp_messagetype == 4'hA)begin//Pdelay_resp_follow_up
                            ov_data    <= {1'b0,8'h04};
                        end
                        else if(rv_ptp_messagetype == 4'h8)begin//follow_up
                            ov_data    <= {1'b0,8'h07};
                        end
                        else if(rv_ptp_messagetype == 4'hc)begin//signaling
                            ov_data    <= {1'b0,8'h08};
                        end 
                        else if(rv_ptp_messagetype == 4'hb)begin//announce
                            ov_data    <= {1'b0,8'h09};
                        end                         
                        else begin
                            ov_data    <= {1'b0,8'hFF};
                        end
                    end
                    6'd16:ov_data    <= {1'b0,osm_id};
                    6'd17:ov_data    <= {1'b0,8'h00};//sequence_id[15:8]
                    6'd18:ov_data    <= {1'b0,8'h00};//sequence_id[7:0]
                    6'd19:ov_data    <= {1'b0,rv_local_count_rx[39:32]};
                    6'd20:ov_data    <= {1'b0,rv_local_count_rx[31:24]};
                    6'd21:ov_data    <= {1'b0,rv_local_count_rx[23:16]};
                    6'd22:ov_data    <= {1'b0,rv_local_count_rx[15:8] };
                    6'd23:ov_data    <= {1'b0,rv_local_count_rx[7:0]  };
                    6'd24:ov_data    <= {1'b0,8'h00};
                    6'd25:ov_data    <= {1'b0,8'h00};
                    6'd26:ov_data    <= {1'b0,8'h00};
                    6'd27:ov_data    <= {1'b0,8'h00};
                    6'd28:ov_data    <= {1'b0,8'h00};
                    6'd29:ov_data    <= {1'b0,8'h00};
                    6'd30:ov_data    <= {1'b0,8'h00};
                    6'd31:begin
                        ov_data           <= {1'b0,8'h00};
                        o_data_fifo_rd    <= 1'b1;  
                        rv_spe_state      <= TRANSMIT_PTPPCF_1ST_CYCLE_S;
                    end
                    default:ov_data <= 9'h00;
                endcase 
            end
            TRANSMIT_PTPPCF_1ST_CYCLE_S:begin        
                o_data_wr           <= 1'b1;
                o_data_fifo_rd      <= 1'b1; 
                ov_data             <= {1'b0,iv_data_fifo_rdata[7:0]};
                rv_spe_state        <= TRANSMIT_PTPPCF_MIDDLE_CYCLE_S;
            end 
            TRANSMIT_PTPPCF_MIDDLE_CYCLE_S:begin   
                o_data_wr           <= 1'b1;
                ov_data             <= iv_data_fifo_rdata;            
                if(iv_data_fifo_rdata[8]) begin  //last cycle.   
                    o_data_fifo_rd      <= 1'b0; 
                    rv_spe_state        <= IDLE_S;
                end
                else begin
                    o_data_fifo_rd      <= 1'b1;
                    rv_spe_state        <= TRANSMIT_PTPPCF_MIDDLE_CYCLE_S;
                end
            end              
            TRANSMIT_NOT_PTPPCF_1ST_CYCLE_S:begin
                o_diagest_fifo_rd   <= 1'b0;
                o_data_wr           <= 1'b1;
                ov_data             <= iv_data_fifo_rdata;
                rv_spe_state        <= TRANSMIT_NOT_PTPPCF_MIDDLE_CYCLE_S;
            end
            TRANSMIT_NOT_PTPPCF_MIDDLE_CYCLE_S:begin
                o_data_wr           <= 1'b1;
                ov_data             <= iv_data_fifo_rdata;
                if(iv_data_fifo_rdata[8])begin  //last cycle.   
                    o_data_fifo_rd      <= 1'b0;
                    rv_spe_state        <= IDLE_S;
                end
                else begin
                    o_data_fifo_rd      <= 1'b1;
                    rv_spe_state        <= TRANSMIT_NOT_PTPPCF_MIDDLE_CYCLE_S;
                end
            end            
            default:begin
                ov_data             <= 9'b0;
                o_data_wr           <= 1'b0;
                
                o_data_fifo_rd      <= 1'b0;
                o_diagest_fifo_rd   <= 1'b0;
                rv_spe_state        <= IDLE_S;
            end
        endcase
    end
end    
endmodule
